package net.sf.nlp.ltag.persistence;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import net.sf.nlp.ltag.data.ArrayKey;
import net.sf.nlp.ltag.data.ExtractedTree;
import net.sf.nlp.ltag.data.LTAGMergedNode;
import net.sf.nlp.ltag.data.LTAGNode;
import net.sf.nlp.ltag.data.LTAGStatistics;
import net.sf.nlp.ltag.data.LTAGTree;
import net.sf.nlp.ltag.data.SuperLTAG;
import net.sf.nlp.ltag.data.LTAGTree.TreeType;
import net.sf.nlp.ltag.extract.LTAGRelation;
import net.sf.nlp.ltag.util.LTAG;

public class TextPersistence implements LTAGPersistence 
{
	protected static Logger logger =  Logger.getLogger(TextPersistence.class);
	private static String FILE_SUPER_LTAG = "super_ltag.txt";
	private static String FILE_EXTRACT_TREE = "extract_tree.txt";
	private static String FILE_SUPER_STAT = "super_stat.txt";
	private static String FILE_MERGED_LTAG = "merged_ltag.txt";
	
	private static int FILTER_MIN_COUNT = 10; 
	
	@Override
	public void createConnection() throws Exception 
	{		
	}

	@Override
	public void close() throws Exception 
	{	
	}

	@Override
	public Map<String, List<LTAGTree>> loadTrees()
	{
		return new TextLoad().loadTrees();
	}

	@Override
	public void saveTrees(List<ExtractedTree> etrees) throws Exception 
	{
		new TextSave().saveTrees(etrees);
	}

	class TextSave
	{
		public void saveTrees(List<ExtractedTree> etrees) throws Exception 
		{
			Map<String, SuperLTAG> ltagMap = convert(etrees);
			
			List<String> sortKeys = new ArrayList<String>();
			sortKeys.addAll(ltagMap.keySet());
			Collections.sort(sortKeys);
			
			List<StatisticRecord> statisticRecords = statistic(ltagMap, sortKeys);
			Collections.sort(statisticRecords);
			
			saveSuperLTAG(sortKeys, ltagMap);
			saveExtractTree(ltagMap, sortKeys);
			saveStatistic(statisticRecords);
			saveMergedLTAG(sortKeys, ltagMap);
		}
		
		private void saveSuperLTAG(List<String> sortKeys, Map<String, SuperLTAG> ltagMap) throws IOException
		{
			File file = new File("c:/" + FILE_SUPER_LTAG);
			BufferedWriter writer = new BufferedWriter(new FileWriter(file));

			String key;
			int count = 0;
			int beginCount = 0;
			for (int i = 0; i < sortKeys.size(); i++)
			{
				key = sortKeys.get(i);
				SuperLTAG superLTAG = ltagMap.get(key);
				LTAGTree superTree = superLTAG.getSuperTree();
				superTree.setId(i + 1l);
				
				count = superLTAG.getEtrees().size();
				
				if (superLTAG.isIgnore() || count < FILTER_MIN_COUNT)
					continue;
				
				beginCount = countBeginSuperLTAG(superLTAG);
				writer.append(superTree.getId().toString()).append(" ").append(String.valueOf(count)).append(" ").append(String.valueOf(beginCount)).append(" ").append(key).append("\r\n");
				
				if (i % 100 == 0)
					writer.flush();
			}

			writer.close();
		}
		
		private int countBeginSuperLTAG(SuperLTAG superLTAG)
		{
			int beginCount = 0;
			
			if (superLTAG.getSuperTree().getType() != TreeType.I || !"IP".equals(superLTAG.getSuperTree().getRoot().getNodeText()))
				return beginCount;
			
			List<ExtractedTree> etrees = superLTAG.getEtrees();
			
			for (ExtractedTree etree : etrees)
			{
				if (etree.isBeginning())
					beginCount++;
			}
			
			return beginCount;
			
		}
		
		private void saveExtractTree(Map<String, SuperLTAG> ltagMap, List<String> sortKeys) throws IOException
		{
			File file = new File("c:/" + FILE_EXTRACT_TREE);
			BufferedWriter writer = new BufferedWriter(new FileWriter(file));

			for (int i = 0; i < sortKeys.size(); i++)
			{
				SuperLTAG superLTAG = ltagMap.get(sortKeys.get(i));
				
				if (superLTAG.isIgnore() || superLTAG.getEtrees().size() < FILTER_MIN_COUNT)
					continue;
			
				
				List<ExtractedTree> etrees = superLTAG.getEtrees();
				
				List<String> savedLexical = new ArrayList<String>();
				for (int j = 0; j < etrees.size(); j++)
				{
					String lexical = etrees.get(j).getAnchor().getWord().getLexical();
					
					if (savedLexical.contains(lexical))
						continue;
					
					savedLexical.add(lexical);
					writer.append(String.valueOf(lexical)).append(" ").append(String.valueOf(i + 1)).append("\r\n");
				}
				
				writer.flush();
			}
			
			writer.close();
		}
		
		private void saveStatistic(List<StatisticRecord> statisticRecords) throws IOException
		{
			File file = new File("c:/" + FILE_SUPER_STAT);
			BufferedWriter writer = new BufferedWriter(new FileWriter(file));

			int count = 0;
			for (StatisticRecord statisticRecord : statisticRecords)
			{
				writer.append(statisticRecord.toString()).append("\r\n");
				
				if (count % 100 == 0)
					writer.flush();
			}

			writer.close();
		}
		
		private Map<String, SuperLTAG> convert(List<ExtractedTree> etrees)
		{
			Map<String, SuperLTAG> ltagMap = new HashMap<String, SuperLTAG>();
			
			for (ExtractedTree etree : etrees)
			{
				try
				{
					String superLTAGString = etree.toSuperLTAG();
					
					SuperLTAG superLTAG = ltagMap.get(superLTAGString);
					
					if (superLTAG == null)
					{
						superLTAG = new SuperLTAG();
						
						LTAGNode root = LTAG.buildLTAGNodeFromText(superLTAGString);
						if (root == null)
							continue;
						
						LTAGTree tree = new LTAGTree();
						tree.setRoot(root);
						tree.validate();
						
						superLTAG.setSuperTree(tree);
						ltagMap.put(superLTAGString, superLTAG);
					}
					
					superLTAG.getEtrees().add(etree);
				}
				catch(Exception ex)
				{
					logger.error("The tree [" + etree + "] is wrong!", ex);
				}
			}
			return ltagMap;
		}
		
		private List<StatisticRecord> statistic(Map<String, SuperLTAG> ltagMap, List<String> sortKeys)
		{
			Map<ArrayKey, List<StatisticRecord>> statisticMap = new HashMap<ArrayKey, List<StatisticRecord>>();
			
			for (int i = 0; i < sortKeys.size(); i++)
			{
				SuperLTAG superLTAG = ltagMap.get(sortKeys.get(i));
				
				if (superLTAG.isIgnore() || superLTAG.getEtrees().size() < FILTER_MIN_COUNT)
					continue;
				
				List<ExtractedTree> etrees = superLTAG.getEtrees();
				
				for (ExtractedTree etree : etrees)
				{
					Map<LTAGNode, List<ExtractedTree>> operatorMap = etree.getOperatorMap();
					
					Iterator<LTAGNode> nodes = operatorMap.keySet().iterator();
					while (nodes.hasNext())
					{
						LTAGNode node = nodes.next();
						List<ExtractedTree> list = operatorMap.get(node);
						
						if (list.size() == 0)
						{
							StatisticRecord statisticRecord = new StatisticRecord(i +1);
							
							statisticRecord.setDestSuperTreeId(-1);
							statisticRecord.setSrcNodeLocation(node.getLocation());
							statisticRecord.setFreq(1);
							statisticRecord.setOperator("*");
							
							addStatisticRecord(statisticMap, statisticRecord);
						}
						else
						{
							for (ExtractedTree et : list)
							{
								SuperLTAG superTemp = ltagMap.get(et.toSuperLTAG());
								
								if (superTemp == null || superTemp.isIgnore() || superTemp.getEtrees().size() < FILTER_MIN_COUNT)
									continue;
								
								StatisticRecord statisticRecord = new StatisticRecord(i +1);
								statisticRecord.setDestSuperTreeId(sortKeys.indexOf(et.toSuperLTAG()) + 1);
								statisticRecord.setSrcNodeLocation(node.getLocation());
								statisticRecord.setFreq(1);
								
								if (et.getType() == TreeType.A)
									statisticRecord.setOperator("*");
								else
									statisticRecord.setOperator("$");
								
								addStatisticRecord(statisticMap, statisticRecord);						
							}
						}
					}
				}
			}
			
			return statistic(statisticMap);
		}
		
		private List<StatisticRecord> statistic(Map<ArrayKey, List<StatisticRecord>> statisticMap)
		{
			List<StatisticRecord> statisticRecords = new ArrayList<StatisticRecord>();
			
			Iterator<ArrayKey> key = statisticMap.keySet().iterator();
			while(key.hasNext())
			{
				long total = 0;
				List<StatisticRecord> list = statisticMap.get(key.next());
				
				for (StatisticRecord r : list)
					total = total + r.getFreq();
				
				for (StatisticRecord r : list)
					r.setTotal(total);
				
				statisticRecords.addAll(list);
			}
			
			return statisticRecords;
		}
		
		private void addStatisticRecord(Map<ArrayKey, List<StatisticRecord>> statisticMap, StatisticRecord statisticRecord)
		{
			ArrayKey key = statisticRecord.getArrayKey();
			List<StatisticRecord> statisticRecords = statisticMap.get(key);
			
			if (statisticRecords == null)
			{
				statisticRecords = new ArrayList<StatisticRecord>();
				statisticMap.put(key, statisticRecords);
			}
			
			int index = statisticRecords.indexOf(statisticRecord);
			
			if (index == -1)
			{
				statisticRecords.add(statisticRecord);
			}
			else
			{
				statisticRecord = statisticRecords.get(index);
				
				statisticRecord.increaseFreq();
			}
		}
		
		private void saveMergedLTAG(List<String> sortKeys, Map<String, SuperLTAG> ltagMap) throws IOException
		{
			File file = new File("c:/" + FILE_MERGED_LTAG);
			BufferedWriter writer = new BufferedWriter(new FileWriter(file));
			
			
			Map<String, List<SuperLTAG>> mergedLTAGMap = buildMergedLTAGMap(sortKeys, ltagMap);
			
			mergeLTAG(mergedLTAGMap);
			
			Iterator<String> i1 = mergedLTAGMap.keySet().iterator();
			while (i1.hasNext())
			{
				String mergedLTAGStr = i1.next();
				List<SuperLTAG> superLTAGs = mergedLTAGMap.get(mergedLTAGStr);
				
				if (superLTAGs.size() < 2)
				{
					LTAGTree superTree = superLTAGs.get(0).getSuperTree();
					writer.append(String.valueOf(superTree.getId())).append(" ").append(superTree.toSuperLTAG()).append("\r\n");
				}
				else
				{
					SuperLTAG mergedLTAG = null;
					for (int index = 0; index < superLTAGs.size(); index++)
					{
						SuperLTAG superLTAG = superLTAGs.get(index);
						
						mergedLTAG = mergeLTAG(mergedLTAG, superLTAG);
					}
					
					writer.append(String.valueOf(-1)).append(" ").append(mergedLTAG.toString()).append("\r\n");
				}
			}

			writer.close();
		}
		
		private Map<String, List<SuperLTAG>> buildMergedLTAGMap(List<String> sortKeys, Map<String, SuperLTAG> ltagMap)
		{
			Map<String, List<SuperLTAG>> mergedLTAGMap = new HashMap<String, List<SuperLTAG>>();
			
			String key = null;
			for (int i = 0; i < sortKeys.size(); i++)
			{
				SuperLTAG superLTAG = ltagMap.get(sortKeys.get(i));
				
				if (superLTAG.isIgnore() || superLTAG.getEtrees().size() < FILTER_MIN_COUNT)
					continue;
				
				key = getSuperLTAGKey(superLTAG);
				
				List<SuperLTAG> superLTAGs = mergedLTAGMap.get(key);
				
				if (superLTAGs == null)
				{
					superLTAGs = new ArrayList<SuperLTAG>();
					mergedLTAGMap.put(key, superLTAGs);
				}
				
				superLTAGs.add(superLTAG);
				mergedLTAGMap.put(key, superLTAGs);
			}
			
			return mergedLTAGMap;
		}
		
		private void mergeLTAG(Map<String, List<SuperLTAG>> mergedLTAGMap)
		{
			Iterator<String> i = mergedLTAGMap.keySet().iterator();
			while (i.hasNext())
			{
				String mergedLTAG = i.next();
				List<SuperLTAG> superLTAGs = mergedLTAGMap.get(mergedLTAG);
				
				if (superLTAGs.size() < 2)
					continue;
				
				for (SuperLTAG superLTAG : superLTAGs)
				{
					LTAGTree ltagTree = superLTAG.getSuperTree();
					replaceSubsitutionLeafNode(ltagTree.getRoot(), ltagTree.getId());
				}
			}
		}
		
		private SuperLTAG mergeLTAG(SuperLTAG mergedLTAG1, SuperLTAG mergedLTAG2)
		{
			if (mergedLTAG1 == null)
				return mergedLTAG2;
			
			List<LTAGMergedNode> mergedNodes1 = mergedLTAG1.getMergedNodes();
			List<LTAGMergedNode> mergedNodes2 = mergedLTAG2.getMergedNodes();
			
			for (int index1 = 0, index2 = 0; index1 < mergedNodes1.size() || index2 < mergedNodes2.size(); index1++, index2++)
			{
				LTAGMergedNode node1 = null;
				LTAGMergedNode node2 = null;
				
				if (index1 < mergedNodes1.size())
					node1 = mergedNodes1.get(index1);
				if (index2 < mergedNodes2.size())
					node2 = mergedNodes2.get(index2);
				
				if (node1 == null)
				{
					String nodePath = node2.getPath();
					int pos = nodePath.lastIndexOf("-");
					String parentPath = nodePath.substring(0, pos);
					
					if (mergedLTAG1.getSuperTree().getId() == 5889)
						System.out.println("debug");
					
					LTAGNode parent = mergedLTAG1.getSuperTree().getNodeByPath(parentPath);
					
					node1 = node2.clone();
					node1.setParent(parent);
					node1.addMergedNode(node2.getMergedNodeMap());
					
					int index = node2.getParent().getChildren().indexOf(node2);
					
					if (node2.getLeftBrother() == null)
						index = 0;
					else if (node2.getRightBrother() == null)
						index = 100;
					
					if (index < parent.getChildren().size())
						parent.getChildren().add(index, node1);
					else
						parent.getChildren().add(node1);
				}
				else if (node2 == null)
				{
					node1.addMergedNode("", mergedLTAG2.getSuperTree().getId());
				}
				else if (!node1.getPath().equals(node2.getPath()))
				{
					node1.addMergedNode("", mergedLTAG2.getSuperTree().getId());
					index2--;
				}
				else if (node1.getPath().equals(node2.getPath()))
				{
					node1.addMergedNode(node2.getMergedNodeMap());
				}
			}
					
			return mergedLTAG1;
		}
		
		private String getSuperLTAGKey(SuperLTAG superLTAG)
		{
			LTAGTree clonedTree = superLTAG.getSuperTree().clone();
			
			removeSubsitutionLeafNode(clonedTree.getRoot());
			
			return clonedTree.toSuperLTAG();
		}
		
		private void removeSubsitutionLeafNode(LTAGNode node)
		{
			if (node.getChildren() != null && node.getChildren().size() > 0)
			{
				Iterator<LTAGNode> i = node.getChildren().iterator();
				
				while (i.hasNext())
				{
					LTAGNode child = i.next();
					
					if ("$".equals(child.getType()))
						i.remove();
					else
						removeSubsitutionLeafNode(child);
				}
			}	
		}
		
		private void replaceSubsitutionLeafNode(LTAGNode node, long superTreeId)
		{
			if (node.getChildren() != null && node.getChildren().size() > 0)
			{
				Iterator<LTAGNode> i = node.getChildren().iterator();
				
				while (i.hasNext())
				{
					LTAGNode child = i.next();
					
					if ("$".equals(child.getType()))
						new LTAGMergedNode(child, superTreeId);
					else
						replaceSubsitutionLeafNode(child, superTreeId);
				}
			}	
		}
		
		class StatisticRecord implements Comparable<StatisticRecord>
		{
			int srcSuperTreeId;
			int destSuperTreeId;
			int srcNodeLocation;
			
			String operator;
			
			long freq;
			long total;
			
			public StatisticRecord(int srcSuperTreeId)
			{
				this.srcSuperTreeId = srcSuperTreeId;
			}
			
			public int hashCode() {
				return srcSuperTreeId;
			}
			
			public int getSrcSuperTreeId() {
				return srcSuperTreeId;
			}

			public int getDestSuperTreeId() {
				return destSuperTreeId;
			}

			public void setDestSuperTreeId(int destSuperTreeId) {
				this.destSuperTreeId = destSuperTreeId;
			}

			public int getSrcNodeLocation() {
				return srcNodeLocation;
			}

			public void setSrcNodeLocation(int srcNodeLocation) {
				this.srcNodeLocation = srcNodeLocation;
			}

			public String getOperator() {
				return operator;
			}

			public void setOperator(String operator) {
				this.operator = operator;
			}

			public long getFreq() {
				return freq;
			}

			public void setFreq(long freq) {
				this.freq = freq;
			}

			public long getTotal() {
				return total;
			}

			public void setTotal(long total) {
				this.total = total;
			}
			
			public void increaseFreq() {
				this.freq++;
			}

			public ArrayKey getArrayKey()
			{
				return new ArrayKey(srcSuperTreeId, srcNodeLocation, operator);
			}
			
			@Override
			public String toString()
			{
				StringBuffer sb = new StringBuffer();
				
				sb.append(srcSuperTreeId).append(" ");
				sb.append(srcNodeLocation).append(" ");
				sb.append(destSuperTreeId).append(" ");
				sb.append(operator).append(" ");
				sb.append(freq).append(" ");
				sb.append(total);
				
				return sb.toString(); 
			}

			@Override
			public boolean equals(Object obj) 
			{
				if (!(obj instanceof StatisticRecord))
					return false;
				
				StatisticRecord statisticRecord = (StatisticRecord)obj;
				
				if (this.srcSuperTreeId != statisticRecord.getSrcSuperTreeId())
					return false;
				if (this.srcNodeLocation != statisticRecord.getSrcNodeLocation())
					return false;
				if (this.destSuperTreeId != statisticRecord.getDestSuperTreeId())
					return false;
				if (!this.operator.equals(statisticRecord.getOperator()))
					return false;
				
				return true;
			}

			@Override
			public int compareTo(StatisticRecord statisticRecord) 
			{
				if (this.srcSuperTreeId != statisticRecord.getSrcSuperTreeId())
					return Integer.valueOf(this.srcSuperTreeId).compareTo(statisticRecord.getSrcSuperTreeId());
				if (this.srcNodeLocation != statisticRecord.getSrcNodeLocation())
					return Integer.valueOf(this.srcNodeLocation).compareTo(statisticRecord.getSrcNodeLocation());
				if (this.destSuperTreeId != statisticRecord.getDestSuperTreeId())
					return Integer.valueOf(this.destSuperTreeId).compareTo(statisticRecord.getDestSuperTreeId());
				if (!this.operator.equals(statisticRecord.getOperator()))
					return String.valueOf(this.operator).compareTo(statisticRecord.getOperator());
				if (this.freq != statisticRecord.getFreq())
					return Long.valueOf(this.freq).compareTo(statisticRecord.getFreq());
				
				return 0;
			}
		}
	}
	
	class TextLoad
	{
		public  Map<String, List<LTAGTree>> loadTrees() 
		{
			Map<String, List<LTAGTree>>  ltagMap = new HashMap<String, List<LTAGTree>>();
			
			try 
			{
				Map<Long, LTAGTree> supertTreeMap = new HashMap<Long, LTAGTree>();
				
				loadSuperTree(supertTreeMap, ltagMap);
				//loadSuperTreeWithWord(supertTreeMap, ltagMap);
				
				loadStatistic();
			}
			catch (Exception e) 
			{
				logger.error(e.toString(), e);
			} 
			
			return ltagMap;
			
		}
		
		private Map<String, List<LTAGTree>> loadSuperTree(Map<Long, LTAGTree> supertTreeMap, Map<String, List<LTAGTree>>  ltagMap) throws Exception
		{
			List<LTAGTree> beginningTrees = new ArrayList<LTAGTree>();
			
			InputStream is = LTAGRelation.class.getResourceAsStream("/parser/" + FILE_SUPER_LTAG);
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			
			String line = null;
			int index1, index2, index3;
			long beginningTreeCount = 0;
			
			while((line = br.readLine()) != null)
			{
				LTAGTree ltagTree = new LTAGTree();
				
				index1 = line.indexOf(" ");
				index2 = line.indexOf(" ", index1 + 1);
				index3 = line.indexOf(" ", index2 + 1);
				
				ltagTree.setId(Long.valueOf(line.substring(0, index1)));
				ltagTree.setCount(Long.valueOf(line.substring(index1+ 1, index2)));
				ltagTree.setBeginCount(Long.valueOf(line.substring(index2+ 1, index3)));
				ltagTree.setRoot(LTAG.buildLTAGNodeFromText(line.substring(index3 + 1)));
			
				ltagTree.validate();
				
				supertTreeMap.put(ltagTree.getId(), ltagTree);
				
				buildLTAGMap(ltagTree.getAnchor().getNodeText(), ltagTree, ltagMap);
				
				if (ltagTree.getType() == TreeType.I && ltagTree.getRoot().getNodeText().startsWith("IP"))
				{
					beginningTreeCount += ltagTree.getBeginCount();
					beginningTrees.add(ltagTree);
				}
			}
			
			br.close();
			
			LTAGStatistics.setBeginningTreeCount(beginningTreeCount);
			for (LTAGTree ltagTree : beginningTrees)
				LTAGStatistics.addStatistic(ltagTree.getId(), null, -1, null, ltagTree.getBeginCount(), beginningTreeCount);
			
			return ltagMap;
		}
		
		private Map<String, List<LTAGTree>> loadSuperTreeWithWord(Map<Long, LTAGTree> supertTreeMap, Map<String, List<LTAGTree>>  ltagMap) throws Exception
		{
			InputStream is = LTAGRelation.class.getResourceAsStream("/parser/" + FILE_EXTRACT_TREE);
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			
			String line = null;
			int index1 = 0;
			long superTreeId;
			while((line = br.readLine()) != null)
			{
				index1 = line.indexOf(" ");
				
				String word = line.substring(0, index1);
				superTreeId = Long.valueOf(line.substring(index1 + 1));
				LTAGTree ltagTree = supertTreeMap.get(superTreeId);
				
				if (ltagTree == null)
					throw new Exception("Can not find the super tree by id :" + superTreeId);
				
				buildLTAGMap(word, ltagTree, ltagMap);
			}
			
			return ltagMap;
		}
		
		private void loadStatistic() throws Exception
		{
			InputStream is = LTAGRelation.class.getResourceAsStream("/parser/" + FILE_SUPER_STAT);
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			
			String line = null;
			while((line = br.readLine()) != null)
			{
				StringTokenizer st = new StringTokenizer(line);
				
				Long srcSuperTreeId = Long.valueOf(st.nextToken());
				Integer srcNodeLocation = Integer.valueOf(st.nextToken());
				Long destSuperTreeId = Long.valueOf(st.nextToken());
				String operator = st.nextToken();
				Long  frequence = Long.valueOf(st.nextToken());
				Long total = Long.valueOf(st.nextToken());
				
				if (destSuperTreeId == -1)
					destSuperTreeId = null;
				
				LTAGStatistics.addStatistic(srcSuperTreeId, destSuperTreeId, srcNodeLocation, operator, frequence, total);
			}
			
			br.close();
		}
		
		private void buildLTAGMap(String key, LTAGTree ltagTree, Map<String, List<LTAGTree>>  ltagMap)
		{
			List<LTAGTree> list = ltagMap.get(key);
			if (list == null)
			{
				list = new ArrayList<LTAGTree>();
				ltagMap.put(key, list);
			}
			
			list.add(ltagTree);
		}
	}
	
	public static void main(String[] args) throws Exception
	{
		TextPersistence persistence = new TextPersistence();
		
		persistence.saveTrees(null);
	}
}
